"use server";

import _ from "lodash";
import env from "@/server/env";
import dayjs from "dayjs";
import { CookieNames } from "@/shared/cookies";
import userJwtService from "@/server/service/user-jwt-service";
import userService from "@/server/service/user-service";
import userPasswordService from "@/server/service/user-password-service";
import { cookies } from "next/headers";
import { A1, A1_NAME } from "@/shared/agreements";
import agreementService from "@/server/service/agreement-service";
import { wrapAction } from "@/server/wrapper";
import AppError from "@/shared/app-error";

const TOKEN_EXPIRE_DAYS = env.auth.tokenExpireDays;

type LoginParams = { username: string; password: string; agreements: string[] };

const cannotLoginError = () => new AppError({ code: "ERR_CANNOT_LOGIN", message: "用户名或密码错误" });

export async function login({ username, password, agreements }: LoginParams) {
  return await wrapAction(async (): Promise<void> => {
    if (!agreements || !agreements.includes(A1)) {
      throw new AppError({ code: "ERR_NO_AGREEMENT", message: `请同意《${A1_NAME}》` });
    }

    const user = await userService.findByUsername(username);
    if (!user) {
      throw cannotLoginError();
    }

    const userPassword = await userPasswordService.findByUserId(user.id);
    if (!userPassword) {
      throw cannotLoginError();
    }

    if (!await userPasswordService.check(password, userPassword.encryptedPassword)) {
      throw cannotLoginError();
    }

    await agreementService.agree({ userId: user.id, agreement: A1 });

    const expireTime = dayjs().add(TOKEN_EXPIRE_DAYS, "days").toDate();
    const jwt = await userJwtService.createJwt(user, expireTime);

    cookies().set(CookieNames.TOKEN, jwt, { expires: expireTime });
  });
}
